package com.whjfxx.terminal.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whjfxx.terminal.biz.enums.YesNoEnum;
import com.whjfxx.terminal.biz.mapper.SysOrganizationMapper;
import com.whjfxx.terminal.biz.param.OrgPageParam;
import com.whjfxx.terminal.biz.param.OrgParam;
import com.whjfxx.terminal.biz.param.OrgTreeParam;
import com.whjfxx.terminal.biz.param.SearchParam;
import com.whjfxx.terminal.biz.service.SysOrganizationService;
import com.whjfxx.terminal.biz.vo.OrgVo;
import com.whjfxx.terminal.commons.TreeVo;
import com.whjfxx.terminal.entity.SysOrganization;
import com.whjfxx.terminal.exceptions.BizException;
import com.whjfxx.terminal.utils.BeanUtils;
import com.whjfxx.terminal.utils.PageUtils;
import com.whjfxx.terminal.utils.QueryUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Created by b.c on 2022/4/14 10:23
 */
@Service
public class SysOrganizationServiceImpl extends ServiceImpl<SysOrganizationMapper, SysOrganization> implements SysOrganizationService {

    @Override
    public Page<OrgVo> pageList(SearchParam<OrgPageParam> searchParam) {


        LambdaQueryWrapper<SysOrganization> wrapper = new LambdaQueryWrapper<>();
        QueryUtil.search(searchParam, OrgPageParam.class, (pageParam) -> {
            if (Objects.isNull(pageParam.getParentId())) {
                wrapper.eq(SysOrganization::getId , -1L);
            }else {
                wrapper.eq(SysOrganization::getParentId , pageParam.getParentId());
            }
            if (StringUtils.isNotBlank(pageParam.getOrganizationCode())) {
                wrapper.like(SysOrganization::getOrganizationCode, pageParam.getOrganizationCode());
            }
            if (StringUtils.isNotBlank(pageParam.getOrganizationName())) {
                wrapper.like(SysOrganization::getOrganizationName, pageParam.getOrganizationName());
            }
        });
        this.page(searchParam, wrapper);
        Page<SysOrganization> page = PageUtils.buildPage(searchParam);
        Page<OrgVo> pageVo = PageUtils.convert(page, OrgVo.class, (src, target) -> {

        });
        return pageVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertSave(OrgParam param) {
        validRepeat(param);

        SysOrganization organization = new SysOrganization();
        BeanUtils.copyProperties(param, organization);
        organization.setStatus(YesNoEnum.YES.status);
        organization.setCreateTime(LocalDateTime.now());
        organization.setUpdateTime(LocalDateTime.now());
        this.save(organization);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSave(OrgParam param) {
        validRepeat(param);

        SysOrganization organization = this.getById(param.getId());
        if (Objects.isNull(organization)) {
            throw BizException.build("机构信息不存在");
        }
        BeanUtils.copyProperties(param, organization);
        organization.setStatus(YesNoEnum.YES.status);
        organization.setUpdateTime(LocalDateTime.now());
        this.updateById(organization);
    }

    @Override
    public void disable(Long id) {
        SysOrganization organization = this.getById(id);
        if (Objects.isNull(organization)) {
            throw BizException.build("机构信息不存在");
        }
        organization.setStatus(YesNoEnum.NO.status);
        organization.setUpdateTime(LocalDateTime.now());
        this.updateById(organization);
    }

    @Override
    public void enable(Long id) {
        SysOrganization organization = this.getById(id);
        if (Objects.isNull(organization)) {
            throw BizException.build("机构信息不存在");
        }
        organization.setStatus(YesNoEnum.YES.status);
        organization.setUpdateTime(LocalDateTime.now());
        this.updateById(organization);
    }

    @Override
    public List<SysOrganization> getByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return this.baseMapper.selectBatchIds(ids);
    }

    @Override
    public List<TreeVo> tree(OrgTreeParam orgTreeParam) {
        LambdaQueryWrapper<SysOrganization> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysOrganization::getStatus, YesNoEnum.YES.status);
        List<SysOrganization> alls = this.list(wrapper);
        if (CollectionUtils.isEmpty(alls)) {
            return Collections.emptyList();
        }

        if (Objects.isNull(orgTreeParam.getParentId())) {
            orgTreeParam.setParentId(-1L);
        }
        return recursiveTree(orgTreeParam.getParentId(), alls);
    }

    /**
     * 递归
     *
     * @param parentId
     * @param alls
     * @return
     */
    private List<TreeVo> recursiveTree(Long parentId, List<SysOrganization> alls) {
        List<SysOrganization> orgs = alls.stream().filter(a -> a.getParentId().equals(parentId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orgs)) {
            return Collections.emptyList();
        }
        List<TreeVo> childrenVos = orgs.stream().map(a -> new TreeVo(a.getId(), a.getOrganizationName())).collect(Collectors.toList());
        for (TreeVo childrenVo : childrenVos) {
            childrenVo.setChildren(recursiveTree(childrenVo.getId(), alls));
        }
        return childrenVos;
    }

    /**
     * 根据编码和名称校验是否重复
     * @param param
     */
    private void validRepeat(OrgParam param){
        // 校验机构编码是否已经存在
        List<SysOrganization> organizations = this.baseMapper.getByCodeOrName(param.getOrganizationCode(), param.getOrganizationName());
        if (CollectionUtils.isNotEmpty(organizations)) {
            boolean codeRepeat = false, nameRepeat = false;
            for (SysOrganization organization : organizations) {
                if (Objects.nonNull(param.getId()) && organization.getId().equals(param.getId())) {
                    continue;
                }
                if (!codeRepeat && param.getOrganizationCode().equals(organization.getOrganizationCode())) {
                    codeRepeat = true;
                }
                if (!nameRepeat && param.getOrganizationName().equals(organization.getOrganizationName())) {
                    nameRepeat = true;
                }
                if (codeRepeat && nameRepeat) {
                    throw BizException.build("机构编码和名称已经存在");
                }
            }
            if (codeRepeat && !nameRepeat) {
                throw BizException.build("机构编码已经存在");
            }
            if (!codeRepeat && nameRepeat) {
                throw BizException.build("机构名称已经存在");
            }
        }
    }
}
